package com.huawei.zyb.taskManager.infrastructure.config;

import com.huawei.zyb.taskManager.domain.shared.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 全局异常处理器
 * 
 * @author Backend Engineer
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
    /**
     * 错误响应对象
     */
    public static class ErrorResponse {
        private String message;
        private String error;
        private int status;
        private LocalDateTime timestamp;
        private String path;
        private Map<String, String> details;
        
        public ErrorResponse(String message, String error, int status, String path) {
            this.message = message;
            this.error = error;
            this.status = status;
            this.path = path;
            this.timestamp = LocalDateTime.now();
            this.details = new HashMap<>();
        }
        
        // Getters and Setters
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        public String getError() { return error; }
        public void setError(String error) { this.error = error; }
        public int getStatus() { return status; }
        public void setStatus(int status) { this.status = status; }
        public LocalDateTime getTimestamp() { return timestamp; }
        public void setTimestamp(LocalDateTime timestamp) { this.timestamp = timestamp; }
        public String getPath() { return path; }
        public void setPath(String path) { this.path = path; }
        public Map<String, String> getDetails() { return details; }
        public void setDetails(Map<String, String> details) { this.details = details; }
    }
    
    /**
     * 处理业务异常
     */
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
        logger.warn("业务异常: {}", e.getMessage());
        
        ErrorResponse errorResponse = new ErrorResponse(
            e.getMessage(),
            "BUSINESS_ERROR",
            HttpStatus.BAD_REQUEST.value(),
            "/api"
        );
        
        return ResponseEntity.badRequest().body(errorResponse);
    }
    
    /**
     * 处理参数校验异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationException(MethodArgumentNotValidException e) {
        logger.warn("参数校验异常: {}", e.getMessage());
        
        ErrorResponse errorResponse = new ErrorResponse(
            "参数校验失败",
            "VALIDATION_ERROR",
            HttpStatus.BAD_REQUEST.value(),
            "/api"
        );
        
        // 收集所有字段错误
        Map<String, String> fieldErrors = e.getBindingResult()
            .getFieldErrors()
            .stream()
            .collect(Collectors.toMap(
                FieldError::getField,
                FieldError::getDefaultMessage,
                (existing, replacement) -> existing
            ));
        
        errorResponse.setDetails(fieldErrors);
        
        return ResponseEntity.badRequest().body(errorResponse);
    }
    
    /**
     * 处理绑定异常
     */
    @ExceptionHandler(BindException.class)
    public ResponseEntity<ErrorResponse> handleBindException(BindException e) {
        logger.warn("绑定异常: {}", e.getMessage());
        
        ErrorResponse errorResponse = new ErrorResponse(
            "参数绑定失败",
            "BIND_ERROR",
            HttpStatus.BAD_REQUEST.value(),
            "/api"
        );
        
        // 收集所有字段错误
        Map<String, String> fieldErrors = e.getBindingResult()
            .getFieldErrors()
            .stream()
            .collect(Collectors.toMap(
                FieldError::getField,
                FieldError::getDefaultMessage,
                (existing, replacement) -> existing
            ));
        
        errorResponse.setDetails(fieldErrors);
        
        return ResponseEntity.badRequest().body(errorResponse);
    }
    
    /**
     * 处理约束违反异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<ErrorResponse> handleConstraintViolationException(ConstraintViolationException e) {
        logger.warn("约束违反异常: {}", e.getMessage());
        
        ErrorResponse errorResponse = new ErrorResponse(
            "约束违反",
            "CONSTRAINT_VIOLATION",
            HttpStatus.BAD_REQUEST.value(),
            "/api"
        );
        
        // 收集所有约束违反信息
        Map<String, String> violations = e.getConstraintViolations()
            .stream()
            .collect(Collectors.toMap(
                violation -> violation.getPropertyPath().toString(),
                ConstraintViolation::getMessage,
                (existing, replacement) -> existing
            ));
        
        errorResponse.setDetails(violations);
        
        return ResponseEntity.badRequest().body(errorResponse);
    }
    
    /**
     * 处理参数类型不匹配异常
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResponseEntity<ErrorResponse> handleTypeMismatchException(MethodArgumentTypeMismatchException e) {
        logger.warn("参数类型不匹配异常: {}", e.getMessage());
        
        ErrorResponse errorResponse = new ErrorResponse(
            String.format("参数 '%s' 的值 '%s' 类型不正确，期望类型: %s", 
                e.getName(), e.getValue(), e.getRequiredType().getSimpleName()),
            "TYPE_MISMATCH",
            HttpStatus.BAD_REQUEST.value(),
            "/api"
        );
        
        return ResponseEntity.badRequest().body(errorResponse);
    }
    
    /**
     * 处理非法参数异常
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<ErrorResponse> handleIllegalArgumentException(IllegalArgumentException e) {
        logger.warn("非法参数异常: {}", e.getMessage());
        
        ErrorResponse errorResponse = new ErrorResponse(
            e.getMessage(),
            "ILLEGAL_ARGUMENT",
            HttpStatus.BAD_REQUEST.value(),
            "/api"
        );
        
        return ResponseEntity.badRequest().body(errorResponse);
    }
    
    /**
     * 处理非法状态异常
     */
    @ExceptionHandler(IllegalStateException.class)
    public ResponseEntity<ErrorResponse> handleIllegalStateException(IllegalStateException e) {
        logger.warn("非法状态异常: {}", e.getMessage());
        
        ErrorResponse errorResponse = new ErrorResponse(
            e.getMessage(),
            "ILLEGAL_STATE",
            HttpStatus.BAD_REQUEST.value(),
            "/api"
        );
        
        return ResponseEntity.badRequest().body(errorResponse);
    }
    
    /**
     * 处理运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException e) {
        logger.error("运行时异常: ", e);
        
        ErrorResponse errorResponse = new ErrorResponse(
            "系统内部错误，请稍后重试",
            "RUNTIME_ERROR",
            HttpStatus.INTERNAL_SERVER_ERROR.value(),
            "/api"
        );
        
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
    }
    
    /**
     * 处理所有其他异常
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGenericException(Exception e) {
        logger.error("未知异常: ", e);
        
        ErrorResponse errorResponse = new ErrorResponse(
            "系统发生未知错误，请联系管理员",
            "UNKNOWN_ERROR",
            HttpStatus.INTERNAL_SERVER_ERROR.value(),
            "/api"
        );
        
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
    }
}